from collections.abc import Callable
from contextlib import asynccontextmanager

from fastapi import FastAPI
from fastapi.applications import AppType
from fastapi.params import Depends
from sqlalchemy import column, func
from starlette.middleware import Middleware

from app.auth.models import Api, GenericPermissions
from app.core.config import settings
from app.core.dependencies import permission_inject
from app.core.dependencies.state_inject import state_inject
from app.core.handlers.database import SessionDep
from app.core.handlers.exceptions import custom_exception_handlers
from app.core.handlers.loggers import logger
from app.core.handlers.permissions import And, IsAdmin, IsAuthorized
from app.core.handlers.response import BaseResponse
from app.core.handlers.routes import core_router
from app.core.middlewares import RequestLogMiddleware
from app.user.models.user import User

# 日志配置
logger.remove()

logger.configure(extra=settings.loguru_config.extra)
for handler in settings.loguru_config.handlers:
    logger.add(**handler)


# 生命周期
@asynccontextmanager
async def lifespan(app_: AppType):
    logger.info(f"Application name '{app_.title}'")
    logger.info(f"Application version '{app_.version}'")
    logger.info("Application server running")
    yield
    logger.info("Application server shutdown")


middlewares = [RequestLogMiddleware]

# 全局注入
dependencies: list[Callable] = [state_inject, permission_inject]

app = FastAPI(
    title=settings.project_name,
    version="0.1.0",
    debug=settings.debug,
    dependencies=[Depends(d) for d in dependencies],
    middleware=[Middleware(m) for m in middlewares],
    exception_handlers=custom_exception_handlers,
    lifespan=lifespan,
)

# 添加路由
app.include_router(core_router, prefix=settings.api_v1_str)


@app.get(
    "/",
    response_model=BaseResponse,
    dependencies=[Depends(And(And(IsAuthorized, IsAdmin), IsAuthorized))],
)
async def hello_fastapi() -> dict | None:
    logger.info("hello fastapi")
    print(1 / 0)
    return {"message": "hello fastapi"}


@app.get("/test")
async def test_api(db: SessionDep) -> dict | None:
    api_query = db.select(func.count(column("id")), skip_permission_check=True).where(
        Api.id == 1
    )
    db.scalar(api_query)
    user_query = db.select(User, skip_permission_check=True).where(User.id == 1)
    db.scalar(user_query)
    permission_query = db.select(GenericPermissions, skip_permission_check=True).where(
        GenericPermissions.id == 2
    )
    db.scalar(permission_query)
    return {}
